package com.sinosoft.system.primary.action;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.sinosoft.system.primary.biz.SysCredentialsBiz;
import com.sinosoft.system.primary.entity.SysCredentials;
import com.sinosoft.system.primary.realm.UUIDGenerator;
import com.sinosoft.system.util.Result;
import com.sinosoft.system.util.imgCode.VerifyCodeUtil;

@RestController  
@RequestMapping("login") 
public class LoginController {
	
	private Logger log = Logger.getLogger(this.getClass());
	
	@Autowired
	private SysCredentialsBiz sysCredentialsBiz;
	
	/** 
     * 获取验证码图片和文本(验证码文本会保存在HttpSession中) 
     */  
    @RequestMapping("/getVerifyCodeImage")  
    public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {  
        //设置页面不缓存  
        response.setHeader("Pragma", "no-cache");  
        response.setHeader("Cache-Control", "no-cache");  
        response.setDateHeader("Expires", 0);  
        String verifyCode = VerifyCodeUtil.generateTextCode(VerifyCodeUtil.TYPE_NUM_ONLY, 4, null);  
        //将验证码放到HttpSession里面  
        request.getSession().setAttribute("verifyCode", verifyCode);  
        log.info("本次生成的验证码为[" + verifyCode + "],已存放到HttpSession中");  
        //设置输出的内容的类型为JPEG图像  
        response.setContentType("image/jpeg");  
        BufferedImage bufferedImage = VerifyCodeUtil.generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE, Color.BLACK, null);  
        //写给浏览器  
        ImageIO.write(bufferedImage, "JPEG", response.getOutputStream());  
    } 
    
    /** 
     * 用户登录 
     */  
    @RequestMapping(value="/login", method=RequestMethod.POST)  
    @CrossOrigin(methods={RequestMethod.POST})
    public ResponseEntity<Result> login(HttpServletRequest request){  
   	
        String username = request.getParameter("username");  
        String password = request.getParameter("password");  
        //获取HttpSession中的验证码  
//        String verifyCode = (String)request.getSession().getAttribute("verifyCode");  
//        //获取用户请求表单中输入的验证码  
//        String submitCode = WebUtils.getCleanParam(request, "verifyCode");  
//        log.debug("用户[" + username + "]登录时输入的验证码为[" + submitCode + "],HttpSession中的验证码为[" + verifyCode + "]");  
//        if (StringUtils.isEmpty(submitCode) || !StringUtils.equals(verifyCode, submitCode.toLowerCase())){  
//            //request.setAttribute("message_login", "验证码不正确");  
//            return new ResponseEntity<Result>(new Result("1","验证码不正确"), HttpStatus.OK);  
//        }  
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);  
        token.setRememberMe(true);  
        log.debug("为了验证登录用户而封装的token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));  
        //获取当前的Subject  
        Subject currentUser = SecurityUtils.getSubject();  
        try {  
            //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查  
            //每个Realm都能在必要时对提交的AuthenticationTokens作出反应  
            //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法  
            log.debug("对用户[" + username + "]进行登录验证..验证开始");  
            currentUser.login(token); 
            log.debug("对用户[" + username + "]进行登录验证..验证通过");
            String credentials = UUIDGenerator.getUUID();
            SysCredentials sysCredentials = new SysCredentials();
            sysCredentials.setUserName(username);
            sysCredentials.setCredentials(credentials);
            sysCredentialsBiz.insertSysCredentials(sysCredentials);
            String jwtToken = credentials;
            //验证码通过
            return new ResponseEntity<Result>(new Result("OK",jwtToken), HttpStatus.OK);  
        }catch(UnknownAccountException uae){  
            log.debug("对用户[" + username + "]进行登录验证..验证未通过,未知账户");
            //request.setAttribute("message_login", "未知账户");
            return new ResponseEntity<Result>(new Result("2","未知账户"), HttpStatus.OK); 
        }catch(IncorrectCredentialsException ice){  
            log.debug("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");  
            //request.setAttribute("message_login", "密码不正确"); 
            return new ResponseEntity<Result>(new Result("3","密码不正确"), HttpStatus.OK);
        }catch(LockedAccountException lae){  
            log.debug("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");  
            //request.setAttribute("message_login", "账户已锁定"); 
            return new ResponseEntity<Result>(new Result("4","账户已锁定"), HttpStatus.OK);
        }catch(ExcessiveAttemptsException eae){  
            log.debug("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");  
            //request.setAttribute("message_login", "用户名或密码错误次数过多"); 
            return new ResponseEntity<Result>(new Result("5","用户名或密码错误次数过多"), HttpStatus.OK);
        }catch(AuthenticationException ae){  
            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景  
            log.debug("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");  
            ae.printStackTrace();  
            //request.setAttribute("message_login", "用户名或密码不正确");  
            return new ResponseEntity<Result>(new Result("6","用户名或密码不正确"), HttpStatus.OK);
        }  
        //验证是否登录成功  
/*        if(currentUser.isAuthenticated()){  
            log.debug("用户[" + username + "]登录认证通过(这里可以进行一些认证通过后的一些系统参数初始化操作)");  
        }else{  
            token.clear();  
        } */ 
    }  
      
      
    /** 
     * 用户登出 
     */  
    @RequestMapping("/logout")  
    public String logout(HttpServletRequest request){  
         SecurityUtils.getSubject().logout();  
         return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/";  
    }

	public SysCredentialsBiz getSysCredentialsBiz() {
		return sysCredentialsBiz;
	}

	public void setSysCredentialsBiz(SysCredentialsBiz sysCredentialsBiz) {
		this.sysCredentialsBiz = sysCredentialsBiz;
	}

}

